﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace RectBar
{
    public partial class RectCBar : UserControl
    {
        /*
         * 基础属性
        */

        /// <summary>
        /// 分段个数
        /// </summary>
        public int BarCount 
        {
            get { return EachBarLength.Count; } 
        }

        /// <summary>
        /// 每个分段的时间长度
        /// </summary>
        public List<int> EachBarTimeLength { get; set; }

        /// <summary>
        /// 每个分段的时间长度
        /// </summary>
        public List<int> EachBarLength {
            get
            {
                return EachBarTimeLength.Select(time => time*RectCBarPanel.PxRatioTime).ToList();
            }
        }

        /// <summary>
        /// 左边界位置
        /// </summary>
        public int MinXlocation { get; set; }

        /// <summary>
        /// 右边界位置
        /// </summary>
        public int MaxXlocation { get; set; }

        /*
         * 绘图相关
         */

        private Graphics mainGraphics;


        /*
         * 构造函数
         */
        public RectCBar()
        {
            InitializeComponent();
            mainGraphics = this.CreateGraphics();
            this.EachBarTimeLength = new List<int>();
            RectCBarPanel.RatioChanged += this.Invalidate;
        }

        /*
         * 私有函数
         */
        private void RectCBar_Load(object sender, EventArgs e)
        {
            MinXlocation = 0;
            MaxXlocation = this.Width;
        }

        private void RectCBar_Paint(object sender, PaintEventArgs e)
        {
            if (BarCount < 1)
            {
                throw new ArgumentException("未指定任何条目宽度");
            }
            if (EachBarLength.Any(length => length < 1))
            {
                throw new ArgumentException("条目宽度不得小于1");
            }
            this.Width = EachBarLength.Sum();
            

            // 填充区域
            int start = 0, end = EachBarLength[0];
            for (int i = 0; i < EachBarLength.Count; i++)
            {
                FillPartRect(start, end, RectHelper.GetBrush(i), i + 1);
                start += EachBarLength[i];
                if (i + 1 == EachBarLength.Count)
                {
                    end = Width;
                }
                else
                {
                    end += EachBarLength[i + 1];
                }
            }
            // 画边框
            DrawBorder();

            // 截去超出范围的部分
            // CutoutOverRigion();

        }

        /// <summary>
        /// 填充分段区域
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="br"></param>
        /// <param name="index">编号（base 1）</param>
        private void FillPartRect(int start, int end,Brush br,int index)
        {
            // 点
            Point leftTop = new Point(start, 0);
            Point leftButtom = new Point(start, this.Height);
            Point rightTop = new Point(end, 0);
            Point rightButtom = new Point(end, this.Height);

            // 矩形路径
            GraphicsPath gpRect = new GraphicsPath();
            gpRect.AddPolygon(new Point[] { leftTop, rightTop, rightButtom, leftButtom });

            // 文字路径
            Point ptFont = new Point((start + end)/2-7, Height/2-6);
            GraphicsPath gpFont = new GraphicsPath();
            gpFont.AddString(index.ToString(),new FontFamily("Arial"),(int)FontStyle.Bold,13, ptFont,StringFormat.GenericDefault);

            // 矩形区域
            Region rgRect = new Region();
            rgRect.MakeEmpty();
            rgRect.Union(gpRect);

            // 文字区域
            Region rgFont = new Region();
            rgFont.MakeEmpty();
            rgFont.Union(gpFont);

            // 填充区域和文字
            mainGraphics.FillRegion(br, rgRect);
            mainGraphics.FillRegion(Brushes.BlanchedAlmond,rgFont);
        }

        /// <summary>
        /// 画边框
        /// </summary>
        private void DrawBorder()
        {
            // 点
            Point leftTop = new Point(0, 0);
            Point leftButtom = new Point(0, this.Height);
            Point rightTop = new Point(this.Width, 0);
            Point rightButtom = new Point(this.Width, this.Height);

            Pen pen = new Pen(Color.Azure,2);
            mainGraphics.DrawLine(pen,leftTop,leftButtom);
            mainGraphics.DrawLine(pen, leftTop, rightTop);
            mainGraphics.DrawLine(pen, leftButtom, rightButtom);
            mainGraphics.DrawLine(pen, rightTop, rightButtom);

        }

        /// <summary>
        /// 截去超出范围的部分
        /// </summary>
        private void CutoutOverRigion()
        {
            if (this.Left < 50)
            {
                // 点
                Point leftTop = new Point(0, 0);
                Point leftButtom = new Point(0, this.Height);
                Point rightTop = new Point(50, 0);
                Point rightButtom = new Point(50, this.Height);

                // 矩形路径
                GraphicsPath gpRect = new GraphicsPath();
                gpRect.AddPolygon(new Point[] { leftTop, rightTop, rightButtom, leftButtom });

                // 矩形区域
                Region rgRect = new Region();
                rgRect.MakeEmpty();
                rgRect.Union(gpRect);


                GraphicsPath path = new GraphicsPath();
                Rectangle r = new Rectangle(0, 0, 50 - this.Left, Height);
                path.AddRectangle(r);

                mainGraphics.SetClip(path);
                mainGraphics.Clear(Color.Transparent);

            }
        }

        private Point mouseOffset; // 用于记录鼠标拖动
        private int mouseClickYpos; // 用于记录鼠标点击时Y轴坐标(屏幕坐标)
        private bool stayStill = false; // 是否要保持静止
        private void RectCBar_MouseDown(object sender, MouseEventArgs e)
        {
            mouseOffset = new Point(-e.X,-e.Y);
            mouseClickYpos = Control.MousePosition.Y;
            stayStill = false;
        }

        private void RectCBar_MouseMove(object sender, MouseEventArgs e)
        {

            RectCBar bar = (RectCBar)sender;
            Point preLocation = bar.Location; // 初始位置

            if (stayStill)
            {
                return;
            }
            if (bar.Location.X < MinXlocation-1)
            {
                stayStill = true;
                bar.Location = new Point(MinXlocation, bar.Location.Y);
                int movePixelX = bar.Location.X - preLocation.X; // X 方向移动的距离
                int movePixelY = bar.Location.Y - preLocation.Y; // Y 方向移动的距离
                if (LocationMoved != null)
                {
                    LocationMoved(movePixelX, movePixelY);
                }
                return;
            }
            if (bar.Location.X > MaxXlocation+1)
            {
                stayStill = true;
                bar.Location = new Point(MaxXlocation, bar.Location.Y);
                int movePixelX = bar.Location.X - preLocation.X; // X 方向移动的距离
                int movePixelY = bar.Location.Y - preLocation.Y; // Y 方向移动的距离
                if (LocationMoved != null)
                {
                    LocationMoved(movePixelX, movePixelY);
                }
                return;
            }


            //bar.Cursor = Cursors.Arrow;//设置拖动时鼠标箭头
            if (e.Button == MouseButtons.Left)
            {
                // Point mousePos = Control.MousePosition; // 普通移动
                Point mousePos = new Point(Control.MousePosition.X,mouseClickYpos); // 限定Y轴的移动
                mousePos.Offset(bar.mouseOffset.X, bar.mouseOffset.Y);//设置偏移
                bar.Location = bar.Parent.PointToClient(mousePos);

                //Console.WriteLine("X:{0};Y:{1}", bar.Location.X, bar.Location.Y);

                int movePixelX = bar.Location.X - preLocation.X; // X 方向移动的距离
                int movePixelY = bar.Location.Y - preLocation.Y; // Y 方向移动的距离
                if (LocationMoved != null)
                {
                    LocationMoved(movePixelX, movePixelY);
                }
            }
        }

        /*
         * 公开函数
         */

        /// <summary>
        /// X,Y方向发生移动事件
        /// </summary>
        public event Action<int,int> LocationMoved;

        /// <summary>
        /// 移动
        /// </summary>
        /// <param name="pixelX">移动的像素点，小于0左移，大于0右移</param>
        /// <param name="pixelY">移动的像素点，小于0上移，大于0下移</param>
        public void XYmove(int pixelX,int pixelY)
        {
            this.Location = new Point(this.Location.X + pixelX, this.Location.Y + pixelY);
        }

        /// <summary>
        /// 复制当前对象
        /// </summary>
        /// <returns>新的RectCBar对象</returns>
        public RectCBar CopyCBar()
        {
            List<int> eachBarTimeLength = EachBarTimeLength.ToArray().ToList();
            RectCBar bar = new RectCBar { EachBarTimeLength = eachBarTimeLength };
            return bar;
        }
    }
}
